package com.linshengjian.snowball.core;

import com.linshengjian.snowball.core.exception.DataEventException;
import com.linshengjian.snowball.core.exception.DataHandlerException;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class DataExecutor {
    private DataWrapper wrapper;
    private Object data;
    private IDataHandler handler;
    private Set<IDataEvent> events;

    private Map<Class, Object> map = new HashMap<>();

    public DataExecutor(DataWrapper wrapper ,Object data, IDataHandler handler, Set<IDataEvent> events) {
        this.wrapper = wrapper;
        this.data = data;
        this.handler = handler;
        this.events = events;
    }

    public void set(Object obj) {
        map.put(obj.getClass(), obj);
    }

    public <T> T get() {
        return (T) data;
    }

    /**
     * 保存数据
     */
    public void save() throws DataHandlerException, DataEventException {
        for (IDataEvent event : this.events) {
            event.saveBefore(this.data);
        }

        this.data = this.handler.save(this.data, this.map);

        for (IDataEvent event : this.events) {
            event.saveAfter(this.data);
        }
    }

    public <T> T add(Object obj, Object ...outreach) throws DataHandlerException {
        DataWrapper wrapper = this.wrapper.getUse(obj.getClass());
        if (wrapper == null)
            throw new DataHandlerException(obj.getClass().getName() + " 与 " + this.data.getClass().getName() + " 没有建立关系");

        Map<Class, Object> map = new HashMap<>();
        for (Object itme: outreach) {
            map.put(itme.getClass(), itme);
        }
        map.put(this.data.getClass(), this.data);

        return (T) wrapper.getInstance(obj).handler.save(obj, map);
    }

    /**
     * 逻辑删除数据
     */
    public void delete() throws DataHandlerException, DataEventException {
        delete(true);
    }

    /**
     * 删除数据
     * @param logic 是否未逻辑删除
     */
    public void  delete(boolean logic) throws DataHandlerException, DataEventException {
        for (IDataEvent event : this.events) {
            event.deleteBefore(this.data);
        }
        this.handler.delete(this.data, logic);
        for (IDataEvent event : this.events) {
            event.deleteAfter(this.data);
        }
    }

    /**
     * 获取使用者数据
     * @param type 使用者数据类型
     * @return
     */
    public Object getUseData(Class type) throws DataHandlerException {
        return wrapper.getUse(type).getHandler().getUseObject(this.data);
    }

    /**
     * 获取外联数据
     * @param type 外联数据类型
     * @return
     * @throws DataHandlerException
     */
    public Object getOutreachData(Class type) throws DataHandlerException {
        Object obj = this.map.get(type);
        if (obj != null)
            return obj;

        DataWrapper wrapper = this.wrapper.getOutreach(type);
        if (wrapper == null)
            throw new DataHandlerException(type.getName() + " 不是 " + this.data.getClass().getName() + " 的主数据类型");

        obj = wrapper.getHandler().getOutreachObject(this.data);

        return obj;
    }
}
